local cmd_uart_id = 1

local cmd_buf = nil
local cmd_decoder = {}
local com_buff = zbuff.create(100)
local response_buff = zbuff.create(100)
uart.setup(cmd_uart_id, 115200)

uart.on(cmd_uart_id, "receive", function(id, len)
    local data = uart.read(id, len, com_buff)
    input_cmd(com_buff)
    com_buff:seek(0)
    if com_buff:len() > 100 then
        com_buff:resize(100)
    end
    --com_buff:del()
end)

function uart_test()
    uart.write(cmd_uart_id, "uart_test")
end

--sys.timerLoopStart(uart_test, 1000)

function cmd_split(str, reps)
    local r = {}
    if str == nil then return nil end
    string.gsub(str, "[^" .. reps .. "]+", function(w) table.insert(r, w) end)
    return r
end

local function print_zbuff(d)
    str = ""
    for i = 0, d:used() - 1 do str = str .. string.format("%02x ", d[i]) end
    print(str)
end

function cmd_crc(indata, start, len)
    local crc = 0
    for i = start, len - 1 do crc = bit.bxor(crc, indata[i]) end

    return crc
end

function decode_snp(indata)
--    print(indata:toStr())
    --  indata=zbuff.create(100, 0)
    --  indata:pack("A", "$snp,opencaster.cnostar.com,50110,SEP01,cnosbas,sbas4u,*2D")
    --$snp,opencaster.cnostar.com,50110,SEP01,cnosbas,sbas4u,1*1C
    local len = indata:used() - 1
    local j = 0
    local n = 1
    local ss = {}

    for i = 0, len do
        v = indata[i]
        if v == string.byte(",") then
            ss[n] = indata:query(j, i - j)
--            print(i, j, n, ss[n])
            n = n + 1
            j = i + 1
        end
    end
--    print("----")
--    print(ss[2])
--    print(ss[3])
--    print(ss[4])
--    print(ss[5])
--    print(ss[6])
--    print(ss[7])
--    print("")

    db_set_ntrip(ss)
    ntrip_reconnect()
    ss=nil
    uart.write(cmd_uart_id, "snp ok\r\n")
end

function decode_gnp(indata)
    response_buff:seek(0)
    response_buff:pack(">AAAAAAAAAAAAAA", "$gnp", ",", ntrip_host, ",", string.format("%d", ntrip_port), ",", ntrip_mp, ",", ntrip_user, ",", ntrip_pw, ",", string.format("%d", ntrip_upgga), ",")
    local crc = cmd_crc(response_buff, 1, response_buff:used())
    response_buff:pack(">A", string.format("*%02X\r\n", crc))
    uart.tx(cmd_uart_id, response_buff)
end

function decode_sjt(indata)
    print(indata:toStr())
    --  indata=zbuff.create(100, 0)
    --  indata:pack("A", "$sjt,47.100.112.218,8808,*5C")
    --$sjt,47.100.112.218,8808,*5C
    local len = indata:used() - 1
    local j = 0
    local n = 1
    local ss = {}

    for i = 0, len do
        v = indata[i]
        if v == string.byte(",") then
            ss[n] = indata:query(j, i - j)
--            print(i, j, n, ss[n])
            n = n + 1
            j = i + 1
        end
    end
--    print("----")
--    print(ss[2])
--    print(ss[3])
--    print("")

    db_set_jts(ss)
    jts_reconnect()
    uart.write(cmd_uart_id, "sjt ok\r\n")
    ss=nil
end

function decode_gjt(indata)
    response_buff:seek(0)
    response_buff:pack(">AAAAAA", "$gjt", ",", jts_host, ",", string.format("%d", jts_port), ",")
    local crc = cmd_crc(response_buff, 1, response_buff:used())
    response_buff:pack(">A", string.format("*%02X\r\n", crc))
    uart.tx(cmd_uart_id, response_buff)
end

function init_cmd()
    cmd_buf = zbuff.create(150, 0)

    cmd_decoder["snp"] = decode_snp
    cmd_decoder["gnp"] = decode_gnp
    cmd_decoder["sjt"] = decode_sjt
    cmd_decoder["gjt"] = decode_gjt

end

init_cmd()
  
function input_cmd(indata)
    --print_zbuff(indata)
    len = indata:used() - 1
    for i = 0, len do
        v = indata[i]
        if cmd_buf:used() == cmd_buf:len() then
                  print("cmd too long")
            cmd_buf:seek(0)
            goto continue
        end

        if v == string.byte("$") then
            cmd_buf:seek(0)
            cmd_buf:writeU8(v)
            --print("fimd head")
        end
        if cmd_buf:used() == 0 then goto continue end

        --	print(i, v, cmd_buf:used())
        if v ~= string.byte("$") then cmd_buf:writeU8(v) end

        if v == string.byte("\r") or v == string.byte("\n") then
            if cmd_buf:used() < 6 then
                --        print("too short")
                cmd_buf:seek(0)
                goto continue
            else
                len = cmd_buf:used()
                crc = cmd_crc(cmd_buf, 1, cmd_buf:used() - 4)
                s = string.format("%02X", crc)

                if (string.byte(s, 1) ~= cmd_buf[len - 3]) or
                    (string.byte(s, 2) ~= cmd_buf[len - 2]) then
                    log.error("cmd crc error: ",sentence)
                    -- print_zbuff(cmd_buf)
                else
                    sentence = cmd_buf:query(1, 3)
                    --print("find cmd ", sentence)
                    local decoder = cmd_decoder[sentence]
                    if decoder ~= nil then decoder(cmd_buf) end
                end

                cmd_buf:seek(0)
            end
        end

        ::continue::
    end
end

-- init_cmd()

-- d=zbuff.create(1000, 0)
-- d:pack("A", "$GNGGA,104157.158,2233.1812,N,11353.1275,E,1,19,0.92,92.9,M,-2.9,M,,*51\n")
-- print_zbuff(d)
-- input_cmd(d)
